package com.gtw;

import com.gtw.aop.DynamicProxy;
import com.gtw.proxy.Proxy;
import com.gtw.proxy.RealSubject;
import com.gtw.proxy.Subject;

import java.lang.reflect.InvocationHandler;

public class Client {

    public static void main(String[] args){
        Subject subject = new Proxy(new RealSubject());
        subject.request();

        System.out.println("--------分割线-------------");

        //使用自己指定的代理
        Subject hardSubject = new RealSubject();
        Subject proxy = hardSubject.getProxy();
        proxy.request();

        System.out.println("--------分割线-------------");

        /**
         * 动态代理
         */
        // 我们要代理的真实对象
        Subject realSubject = new RealSubject();
        // 我们要代理哪个真实对象，就将该对象传进去，最后是通过该真实对象来调用其方法的
        InvocationHandler handler = new DynamicProxy(realSubject);
		/*
		 * 通过Proxy的newProxyInstance方法来创建我们的代理对象，看看其三个参数
 		 * 第一个参数handler.getClass().getClassLoader()，这里使用handler这个类的ClassLoader对象来加载我们的代理对象
		 * 第二个参数realSubject.getClass().getInterfaces()，这里为代理对象提供的接口是真实对象所实行的接口，表示我要代理的是该真实对象，这样就能调用这组接口中的方法了
		 * 第三个参数handler，我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
		 */
        /**
         * Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象，它并不是我们的InvocationHandler类型，
         * 也不是我们定义的那组接口的类型，而是在运行是动态生成的一个对象，并且命名方式都是这样的形式，以$开头，proxy为中，最后一个数字表示对象的标号。
         */
        Subject proxySubject = (Subject) java.lang.reflect.Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);
        System.out.println(proxySubject.getClass().getName());
        /**
         * 通过代理对象来调用方法的时候，起实际就是委托由其关联到的 handler 对象的invoke方法中来调用，并不是自己来真实调用，而是通过代理的方式来调用的。
         */
        proxySubject.request();

    }
}
